/**
 * Copyright (C) 2021 - 2031 O-Cubes Co., Ltd.
 */

/****************************************************************
 *  @file    hal_api.c
 *  @brief   HAL layer interface source file
 *  @version v1.0
 *  @date    03. Apr. 2023
 ****************************************************************/

#include <string.h>

#include "common.h"
#include "hal_api.h"
#include "error.h"
#include "drv.h"
#include "sha256.h"
#include "sm4.h"
#include "aes.h"

#define I2C_ADDR_LEN                       (sizeof(I2c_Addr_t))
#define I2C_ADDR_H8(addr16)                ((addr16 >> 8) & 0xFF)
#define I2C_ADDR_L8(addr16)                (addr16 & 0xFF)
#define SEC_HASH_VAL_LEN                   32

int32_t Hal_Pcl_FuncSet(Pad_Id_t id, Pcl_Pin_Func func)
{
#ifdef CONFIG_SDK_PCL
	pcl_func_select(id, func);

	return RET_OK;
#else
	return RET_OK;
#endif
}

Pcl_Pin_Func Hal_Pcl_FuncGet(Pad_Id_t id)
{
#ifdef CONFIG_SDK_PCL
	return pcl_func_get(id);
#else
	return RET_OK;
#endif
}

void Hal_Pcl_PdPuSet(Pad_Id_t id, Pcl_Pd_Pu_Set cfg)
{
#ifdef CONFIG_SDK_PCL
	pcl_pd_pu_set(id, cfg);
#endif
}

void Hal_Pcl_OutputSet(Pad_Id_t id, Pcl_Output_Set cfg)
{
#ifdef CONFIG_SDK_PCL
	pcl_pin_output_set(id, cfg);
#endif
}

int32_t Hal_Gpio_GetVal(Gpio_Port port, Gpio_Pin pin)
{
#ifdef CONFIG_SDK_GPIO
	int32_t ercd = E_OK;
	uint32_t val;
	uint32_t bitmask = BIT(pin);
	DRV_CHECK_EXP(((port == GPIO_PORT_A) | (port == GPIO_PORT_B)), E_PAR);

	DEV_GPIO_PTR gpio_ptr = gpio_get_dev(eGPIO_DEV_OBJ_0, port);
	DRV_CHECK_EXP(gpio_ptr != NULL, E_OBJ);

	ercd = gpio_ptr->gpio_control(GPIO_CMD_SET_BIT_DIR_INPUT, CONV2VOID(&bitmask));
	DRV_CHECK_EXP(ercd == E_OK, E_SYS);

	ercd = gpio_ptr->gpio_read(&val, BIT(pin));
	DRV_CHECK_EXP(ercd == E_OK, E_SYS);

	val >>= pin;
	return val;

error_exit:
	return ercd;
#else
	return 0;
#endif
}

int32_t Hal_Gpio_SetVal(Gpio_Port port, Gpio_Pin pin,  Gpio_Pin_Val val)
{
#ifdef CONFIG_SDK_GPIO
	int32_t ercd = E_OK;
	uint32_t bitmask = BIT(pin);
	DRV_CHECK_EXP(((port == GPIO_PORT_A) | (port == GPIO_PORT_B)), E_PAR);

	DEV_GPIO_PTR gpio_ptr = gpio_get_dev(eGPIO_DEV_OBJ_0, port);
	DRV_CHECK_EXP(gpio_ptr != NULL, E_OBJ);

	ercd = gpio_ptr->gpio_control(GPIO_CMD_SET_BIT_DIR_OUTPUT, CONV2VOID(&bitmask));
	DRV_CHECK_EXP(ercd == E_OK, E_SYS);

	ercd = gpio_ptr->gpio_write(val << pin, BIT(pin));
	DRV_CHECK_EXP(ercd == E_OK, E_SYS);

error_exit:
	return ercd;
#else
	return RET_OK;
#endif
}

int32_t Hal_Gpio_Int_Enable(Gpio_Port port, Gpio_Pin pin, DEV_GPIO_INT_CFG_PTR cfg_param, DEV_GPIO_BIT_ISR_PTR isr_param)
{
#ifdef CONFIG_SDK_GPIO
	int32_t ercd = E_OK;
	uint32_t bitmask = BIT(pin);
	DRV_CHECK_EXP(port == GPIO_PORT_A, E_PAR);

	DEV_GPIO_PTR gpio_ptr = gpio_get_dev(eGPIO_DEV_OBJ_0, port);
	DRV_CHECK_EXP(gpio_ptr != NULL, E_OBJ);

	ercd = gpio_ptr->gpio_control(GPIO_CMD_SET_BIT_DIR_INPUT, CONV2VOID(&bitmask));
	DRV_CHECK_EXP(ercd == E_OK, E_SYS);

	ercd = gpio_ptr->gpio_control(GPIO_CMD_SET_BIT_INT_CFG, cfg_param);
	DRV_CHECK_EXP(ercd == E_OK, E_SYS);

	ercd = gpio_ptr->gpio_control(GPIO_CMD_SET_BIT_ISR, isr_param);
	DRV_CHECK_EXP(ercd == E_OK, E_SYS);

	ercd = gpio_ptr->gpio_control(GPIO_CMD_ENA_BIT_INT,  CONV2VOID(&bitmask));
	DRV_CHECK_EXP(ercd == E_OK, E_SYS);

error_exit:
	return ercd;
#else
	return RET_OK;
#endif
}

int32_t Hal_Gpio_Int_Disable(Gpio_Port port, Gpio_Pin pin)
{
#ifdef CONFIG_SDK_GPIO
	int32_t ercd = E_OK;
	uint32_t bitmask = BIT(pin);
	DRV_CHECK_EXP(port == GPIO_PORT_A, E_PAR);

	DEV_GPIO_PTR gpio_ptr = gpio_get_dev(eGPIO_DEV_OBJ_0, port);
	DRV_CHECK_EXP(gpio_ptr != NULL, E_OBJ);

	ercd = gpio_ptr->gpio_control(GPIO_CMD_DIS_BIT_INT, CONV2VOID(&bitmask));
	DRV_CHECK_EXP(ercd == E_OK, E_SYS);

error_exit:
	return ercd;
#else
	return RET_OK;
#endif

}
void Hal_Console_PutChar(char c)
{
#ifdef CONFIG_SDK_UART
	Hal_Uart_PutChar(UART_ID_3, c);  //mark
#endif
}

int32_t Hal_Uart_SetBaud(Uart_Id uart, uint32_t baudrate)
{
#ifdef CONFIG_SDK_UART
	int32_t ercd = E_OK;

	DEV_UART_PTR uart_ptr = uart_get_dev(uart);

	DRV_CHECK_EXP(uart_ptr != NULL, E_OBJ);

	ercd = uart_ptr->uart_control(UART_CMD_SET_BAUD, CONV2VOID(baudrate));
	DRV_CHECK_EXP(ercd == E_OK, E_SYS);

error_exit:
	return ercd;
#else
	return RET_OK;
#endif
}

int32_t Hal_Uart_PutChar(Uart_Id uart, char c)
{
#ifdef CONFIG_SDK_UART
	int32_t ercd = E_OK;

	DEV_UART_PTR uart_ptr = uart_get_dev(uart);

	DRV_CHECK_EXP(uart_ptr != NULL, E_OBJ);

	ercd = uart_ptr->uart_write(&c, 1);
	DRV_CHECK_EXP(ercd == 1, E_SYS);

error_exit:
	return ercd;
#else
	return RET_OK;
#endif
}

inline char Hal_Console_GetChar(void)
{
#ifdef CONFIG_SDK_UART
	return Hal_Uart_GetChar(UART_ID_0);
#else
	return 0;
#endif
}

char Hal_Uart_GetChar(Uart_Id uart)
{
#ifdef CONFIG_SDK_UART
	int32_t ercd = E_OK;
	char c;

	DEV_UART_PTR uart_ptr = uart_get_dev(uart);

	DRV_CHECK_EXP(uart_ptr != NULL, E_OBJ);

	ercd = uart_ptr->uart_read(&c, 1);
	DRV_CHECK_EXP(ercd == 1, E_SYS);

	return c;

error_exit:
	return ercd;
#else
	return RET_OK;
#endif
}

void Hal_Console_PutStr(const char *str, uint32_t len)
{
#ifdef CONFIG_SDK_UART
	Hal_Uart_PutStr(UART_ID_0, str, len);
#endif
}

int32_t Hal_Uart_PutStr(Uart_Id uart, const char *str, uint32_t len)
{
#ifdef CONFIG_SDK_UART
	int32_t ercd = E_OK;

	DEV_UART_PTR uart_ptr = uart_get_dev(uart);

	DRV_CHECK_EXP(uart_ptr != NULL, E_OBJ);
	DRV_CHECK_EXP(str != NULL, E_PAR);

	ercd = uart_ptr->uart_write(str, len);
	DRV_CHECK_EXP(ercd == len, E_SYS);

error_exit:
	return ercd;
#else
	return RET_OK;
#endif
}

void Hal_Console_GetStr(char *str, uint32_t len)
{
#ifdef CONFIG_SDK_UART
	Hal_Uart_GetStr(UART_ID_0, str, len);
#endif
}

int32_t Hal_Uart_GetStr(Uart_Id uart, char *str, uint32_t len)
{
#ifdef CONFIG_SDK_UART
	int32_t ercd = E_OK;

	DEV_UART_PTR uart_ptr = uart_get_dev(uart);

	DRV_CHECK_EXP(uart_ptr != NULL, E_OBJ);
	DRV_CHECK_EXP(str != NULL, E_PAR);

	ercd = uart_ptr->uart_read(str, len);
	DRV_CHECK_EXP(ercd == len, E_SYS);

error_exit:
	return ercd;
#else
	return RET_OK;
#endif
}

int32_t Hal_Uart_Dma_Write(Uart_Id uart, uint8_t *w_buf, uint32_t w_len)
{
#if defined(CONFIG_SDK_UART) && defined(CONFIG_SDK_DMA)
	int32_t ercd = E_OK;
	DEV_UART_PTR uart_ptr = uart_get_dev(uart);
	DRV_CHECK_EXP(uart_ptr != NULL, E_OBJ);
	DRV_CHECK_EXP(w_buf != NULL, E_PAR);

	ercd = dw_uart_dma_write(uart_ptr, w_buf, w_len);
error_exit:
	return ercd;
#else
	return RET_OK;
#endif
}

int32_t Hal_Uart_Dma_Read(Uart_Id uart, uint8_t *r_buf, uint32_t r_len)
{
#if defined(CONFIG_SDK_UART) && defined(CONFIG_SDK_DMA)
	int32_t ercd = E_OK;
	DEV_UART_PTR uart_ptr = uart_get_dev(uart);
	DRV_CHECK_EXP(uart_ptr != NULL, E_OBJ);
	DRV_CHECK_EXP(r_buf != NULL, E_PAR);

	ercd = dw_uart_dma_read(uart_ptr, r_buf, r_len);
error_exit:
	return ercd;
#else
	return RET_OK;
#endif

}

int32_t Hal_Uart_Request_Dma_Chan(Uart_Id uart, uint8_t tx_chan, uint8_t rx_chan)
{
#if defined(CONFIG_SDK_SPICTRL) && defined(CONFIG_SDK_DMA)
	int32_t ercd = E_OK;
	DEV_UART_PTR uart_ptr = uart_get_dev(uart);

	DRV_CHECK_EXP(uart_ptr != NULL, E_OBJ);

	DEV_UART_INFO *uart_info = &uart_ptr->uart_info;
	uart_info->hasdma = true;
	uart_info->drqline = DMA_UART_DEV + uart;
	uart_info->dma_tx_chan = tx_chan;
	uart_info->dma_rx_chan = rx_chan;

	ercd = uart_ptr->uart_control(UART_CMD_REQ_DMA_CHAN, NULL);
	DRV_CHECK_EXP(ercd == E_OK, ercd);

error_exit:
	return ercd;
#else
	return RET_OK;
#endif
}

Sys_Timestamp_t Hal_Cnt_GetTimestamp(void)
{
#ifdef CONFIG_SDK_SYSCNT
	uint64_t cnt_val = 0;
	cnt_val = syscnt_read_counter();

	return syscnt_tick_to_usec(cnt_val);
#else
	return 0;
#endif
}

void Hal_Cnt_DelayUs(uint32_t usec)
{
#ifdef CONFIG_SDK_SYSCNT
	syscnt_udelay(usec);
#endif
}

void Hal_Cnt_DelayMs(uint32_t msec)
{
#ifdef CONFIG_SDK_SYSCNT
	syscnt_mdelay(msec);
#endif
}

int32_t Hal_Timer_StartOneshot(Timer_Id timer, uint32_t ms, Hal_Timer_Callback cb)
{
#ifdef CONFIG_SDK_TIMER
	int32_t ercd = E_OK;
	DEV_TIMER_CFG timer_cfg;
	uint64_t count = ((uint64_t)ms * get_mod_clk_rate(CRG_MOD_TIMER0 + timer))/TIME_MS_VAL;
	DEV_TIMER_PTR timer_ptr = timer_get_dev(timer);

	DRV_CHECK_EXP(timer_ptr != NULL, E_OBJ);

	timer_cfg.mode = DEV_TIMER_MODE_ONESHOT_TMR;
	timer_cfg.count_low = count & 0xFFFFFFFF;
	timer_cfg.count_high = count >> 32;
	timer_cfg.int_ch_handler = cb;
	ercd = timer_ptr->timer_control(TIMER_CMD_SET_CFG, CONV2VOID(&timer_cfg));

	DRV_CHECK_EXP(ercd == E_OK, E_SYS);

error_exit:
	return ercd;
#else
	return RET_OK;
#endif
}

int32_t Hal_Timer_StartPeriod(Timer_Id timer, uint32_t us, Hal_Timer_Callback cb)
{
#ifdef CONFIG_SDK_TIMER
	int32_t ercd = E_OK;
	DEV_TIMER_CFG timer_cfg;
	uint64_t count = ((uint64_t)us * get_mod_clk_rate(CRG_MOD_TIMER0 + timer))/TIME_US_VAL;
	DEV_TIMER_PTR timer_ptr = timer_get_dev(timer);

	DRV_CHECK_EXP(timer_ptr != NULL, E_OBJ);

	timer_cfg.mode = DEV_TIMER_MODE_PERIODIC_TMR;
	timer_cfg.count_low = count & 0xFFFFFFFF;
	timer_cfg.count_high = count >> 32;
	timer_cfg.int_ch_handler = cb;
	ercd = timer_ptr->timer_control(TIMER_CMD_SET_CFG, CONV2VOID(&timer_cfg));

	DRV_CHECK_EXP(ercd == E_OK, E_SYS);

error_exit:
	return ercd;
#else
	return RET_OK;
#endif
}

int32_t Hal_Timer_StopPeriod(Timer_Id timer)
{
#ifdef CONFIG_SDK_TIMER
	int32_t ercd = E_OK;
	DEV_TIMER_CFG timer_cfg;
	DEV_TIMER_PTR timer_ptr = timer_get_dev(timer);

	DRV_CHECK_EXP(timer_ptr != NULL, E_OBJ);

	timer_cfg.mode = DEV_TIMER_MODE_CLOSE;
	timer_cfg.count_low = 0;
	timer_cfg.count_high = 0;
	timer_cfg.int_ch_handler = NULL;
	ercd = timer_ptr->timer_control(TIMER_CMD_SET_CFG, CONV2VOID(&timer_cfg));

	DRV_CHECK_EXP(ercd == E_OK, E_SYS);

error_exit:
	return ercd;
#else
	return RET_OK;
#endif
}

void Hal_Rtc_SetDatetime(Datetime_t_Ptr tm)
{
#ifdef CONFIG_SDK_RTC
	rtc_set_time(tm);
#else
	
#endif
}

int32_t Hal_Rtc_GetDatetime(Datetime_t_Ptr tm)
{
#ifdef CONFIG_SDK_RTC
	return rtc_get_time(tm);
#else
	return RET_OK;
#endif
}

void Hal_Rtc_Start(void)
{
#ifdef CONFIG_SDK_RTC
	rtc_start();
#endif
}

void Hal_Rtc_Stop(void)
{
#ifdef CONFIG_SDK_RTC
	irq_disable(RTC_IRQn);
	rtc_stop();
#endif
}

int32_t Hal_Rtc_SetAlarm(uint32_t sec)
{
#ifdef CONFIG_SDK_RTC
	rtc_set_alarm(sec);
	irq_enable(RTC_IRQn);
	return 0;
#else
	return RET_OK;
#endif
}

void Hal_Rtc_RegisterCb(Hal_Rtc_Callback cb)
{
#ifdef CONFIG_SDK_RTC
	rtc_register_callback(cb);
#endif
}

int32_t Hal_Pwm_Start(Pwm_Id pwm, uint32_t duty_cycle, uint32_t hz)
{
#ifdef CONFIG_SDK_PWM
	return pwm_start(pwm, duty_cycle, hz);
#else
	return RET_OK;
#endif
}

int32_t Hal_Pwm_Stop(Pwm_Id pwm)
{
#ifdef CONFIG_SDK_PWM
	return pwm_stop(pwm);
#else
	return RET_OK;
#endif
}

#ifdef SPIFLASH_XIP_EN
__ATTR_RAM_CODE int32_t Hal_Flash_Write(Flash_Addr_t addr, uint32_t size, const uint8_t *data)
#else
int32_t Hal_Flash_Write(Flash_Addr_t addr, uint32_t size, const uint8_t *data)
#endif
{
#ifdef CONFIG_SDK_QSPIFLASH
	int32_t ercd = E_OK;
	
	sfud_xip_dis();
	ercd = sfud_write(addr, size, data);
	sfud_xip_en();
	return ercd;
#else
	return RET_OK;
#endif
}

#ifdef SPIFLASH_XIP_EN
__ATTR_RAM_CODE int32_t Hal_Flash_Read(Flash_Addr_t addr, uint32_t size, uint8_t *data)
#else
int32_t Hal_Flash_Read(Flash_Addr_t addr, uint32_t size, uint8_t *data)
#endif
{
#ifdef CONFIG_SDK_QSPIFLASH
	int32_t ercd = E_OK;
	
	sfud_xip_dis();
	ercd = sfud_read(addr, size, data);
	sfud_xip_en();
	return ercd;
#else
	return RET_OK;
#endif
}

#ifdef SPIFLASH_XIP_EN
__ATTR_RAM_CODE int32_t Hal_Flash_Erase(Flash_Addr_t addr, uint32_t size)
#else
int32_t Hal_Flash_Erase(Flash_Addr_t addr, uint32_t size)
#endif
{
#ifdef CONFIG_SDK_QSPIFLASH
	int32_t ercd = E_OK;
	
	sfud_xip_dis();
	ercd = sfud_erase(addr, size);
	sfud_xip_en();
	return ercd;
#else
	return RET_OK;
#endif
}

#ifdef SPIFLASH_XIP_EN
__ATTR_RAM_CODE int32_t Hal_Flash_ChipErase(void)
#else
int32_t Hal_Flash_ChipErase(void)
#endif
{
#ifdef CONFIG_SDK_QSPIFLASH
	int32_t ercd = E_OK;
	
	sfud_xip_dis();
	ercd = sfud_chip_erase();
	sfud_xip_en();
	return ercd;
#else
	return RET_OK;
#endif
}

#ifdef SPIFLASH_XIP_EN
__ATTR_RAM_CODE int32_t Hal_Flash_EraseWrite(Flash_Addr_t addr, uint32_t size, const uint8_t *data)
#else
int32_t Hal_Flash_EraseWrite(Flash_Addr_t addr, uint32_t size, const uint8_t *data)
#endif
{
#ifdef CONFIG_SDK_QSPIFLASH
	int32_t ercd = E_OK;
	
	sfud_xip_dis();
	ercd = sfud_erase_write(addr, size, data);
	sfud_xip_en();
	return ercd;
#else
	return RET_OK;
#endif
}

//void Hal_Flash_XipEn(void)
//{
//#ifdef CONFIG_SDK_QSPIFLASH
//	sfud_xip_en();
//#endif
//}

//void Hal_Flash_XipDis(void)
//{
//#ifdef CONFIG_SDK_QSPIFLASH
//	sfud_xip_dis();
//#endif
//}

int32_t Hal_Spi_Transfer(Spi_Cfg_t_Ptr ptr, uint8_t *w_buf, uint32_t w_len, uint8_t *r_buf, uint32_t r_len)
{
#ifdef CONFIG_SDK_SPICTRL
	int32_t ercd = E_OK;
	DEV_SPI_PTR spi_ptr = spi_get_dev(ptr->devid);

	DRV_CHECK_EXP(spi_ptr != NULL, E_OBJ);
	DRV_CHECK_EXP(w_buf != NULL, E_PAR);

	spi_ptr->cs = ptr->spi_cs;
	ercd = dw_spi_write_read(spi_ptr, w_buf, w_len, r_buf, r_len);

error_exit:
	return ercd;
#else
	return RET_OK;
#endif
}

int32_t Hal_Spi_Request_Dma_Chan(Spi_Cfg_t_Ptr ptr, uint8_t tx_chan, uint8_t rx_chan)
{
#if defined(CONFIG_SDK_SPICTRL) && defined(CONFIG_SDK_DMA)
	int32_t ercd = E_OK;
	DEV_SPI_PTR spi_ptr = spi_get_dev(ptr->devid);

	DRV_CHECK_EXP(spi_ptr != NULL, E_OBJ);

	DEV_SPI_INFO_PTR spi_info = &spi_ptr->spi_info;
	spi_info->hasdma = true;
	spi_info->drqline = DMA_SPI_DEV + ptr->devid;
	spi_info->dma_tx_chan = tx_chan;
	spi_info->dma_rx_chan = rx_chan;

	ercd = spi_ptr->spi_control(SPI_CMD_REQ_DMA_CHAN, NULL);
	DRV_CHECK_EXP(ercd == E_OK, ercd);

error_exit:
	return ercd;
#else
	return RET_OK;
#endif
}


int32_t Hal_I2c_Write(I2c_Id i2c, uint8_t *w_buf, uint32_t w_size)
{
#ifdef CONFIG_SDK_I2C
	int32_t ercd = E_OK;
	int32_t len = 0;

	DEV_I2C_PTR i2c_ptr = i2c_get_dev(i2c);
	DRV_CHECK_EXP(i2c_ptr != NULL, E_OBJ);
	DRV_CHECK_EXP(w_buf != NULL, E_PAR);

	len = i2c_ptr->i2c_write(w_buf, w_size);
	DRV_CHECK_EXP(len == w_size, E_SYS);

error_exit:
	return ercd;
#else
	return RET_OK;
#endif
}

int32_t Hal_I2c_Read(I2c_Id i2c, uint8_t *r_buf, uint32_t r_size)
{
#ifdef CONFIG_SDK_I2C
	int32_t ercd = E_OK;
	int32_t len = 0;

	DEV_I2C_PTR i2c_ptr = i2c_get_dev(i2c);
	DRV_CHECK_EXP(i2c_ptr != NULL, E_OBJ);
	DRV_CHECK_EXP(r_buf != NULL, E_PAR);

	len = i2c_ptr->i2c_read(r_buf, r_size);
	DRV_CHECK_EXP(len == r_size, E_SYS);

error_exit:
	return ercd;
#else
	return RET_OK;
#endif
}

int32_t Hal_I2c_Tar_Add_Cfg(I2c_Id i2c, uint32_t tar_addr)
{
#ifdef CONFIG_SDK_I2C
	int32_t ercd = E_OK;
	DEV_I2C_PTR i2c_ptr = i2c_get_dev(i2c);
	DRV_CHECK_EXP(i2c_ptr != NULL, E_OBJ);

	ercd = i2c_ptr->i2c_control(I2C_CMD_MST_SET_TAR_ADDR, CONV2VOID(tar_addr));
	DRV_CHECK_EXP(ercd == E_OK, ercd);

error_exit:
	return ercd;
#else
	return RET_OK;
#endif
}

int32_t Hal_I2c_Request_Dma_Chan(I2c_Id i2c, uint8_t tx_chan, uint8_t rx_chan)
{
#if defined(CONFIG_SDK_I2C) && defined(CONFIG_SDK_DMA)
	int32_t ercd = E_OK;
	DEV_I2C_PTR i2c_ptr = i2c_get_dev(i2c);
	DRV_CHECK_EXP(i2c_ptr != NULL, E_OBJ);
	DEV_I2C_INFO_PTR i2c_info = &i2c_ptr->i2c_info;
	i2c_info->hasdma = true;
	i2c_info->drqline = DMA_I2C_DEV + i2c;
	i2c_info->dma_tx_chan = tx_chan;
	i2c_info->dma_rx_chan = rx_chan;

	ercd = i2c_ptr->i2c_control(I2C_CMD_REQ_DMA_CHAN, NULL);
	DRV_CHECK_EXP(ercd == E_OK, ercd);

error_exit:
	return ercd;
#else
	return RET_OK;
#endif
}

int32_t Hal_I2c_Dma_Write(I2c_Id i2c, uint16_t *w_buf, uint32_t w_len)
{
#if defined(CONFIG_SDK_I2C) && defined(CONFIG_SDK_DMA)
	int32_t ercd = E_OK;
	DEV_I2C_PTR i2c_ptr = i2c_get_dev(i2c);
	DRV_CHECK_EXP(i2c_ptr != NULL, E_OBJ);
	DEV_I2C_INFO_PTR i2c_info = &i2c_ptr->i2c_info;
	DRV_CHECK_EXP(i2c_info->hasdma == true, E_FAILURE);

	dw_i2c_dma_write(i2c_ptr, w_buf, w_len);

error_exit:
	return ercd;
#else
	return RET_OK;
#endif
}

int32_t Hal_I2c_Dma_Read(I2c_Id i2c, uint16_t *w_buf, uint32_t w_len, uint32_t *r_buf, uint32_t r_len)
{
	#if defined(CONFIG_SDK_I2C) && defined(CONFIG_SDK_DMA)
	int32_t ercd = E_OK;
	DEV_I2C_PTR i2c_ptr = i2c_get_dev(i2c);
	DRV_CHECK_EXP(i2c_ptr != NULL, E_OBJ);
	DEV_I2C_INFO_PTR i2c_info = &i2c_ptr->i2c_info;
	DRV_CHECK_EXP(i2c_info->hasdma == true, E_FAILURE);

	dw_i2c_dma_read(i2c_ptr, w_buf, w_len, r_buf, r_len);

error_exit:
	return ercd;
#else
	return RET_OK;
#endif
}

void Hal_Wdt_Start(Wdt_Id wdt, uint32_t timeout)
{
#ifdef CONFIG_SDK_WDT
	wdt_switch(wdt);
	wdt_start(timeout);
#endif
}

void Hal_Wdt_Stop(Wdt_Id wdt)
{
#ifdef CONFIG_SDK_WDT
	wdt_switch(wdt);
	wdt_stop();
#endif
}

void Hal_Wdt_Kick(Wdt_Id wdt)
{
#ifdef CONFIG_SDK_WDT
	wdt_switch(wdt);
	wdt_ping();
#endif
}

void Hal_Wdt_RegisterCb(Hal_Wdt_Callback cb)
{
#ifdef CONFIG_SDK_WDT
	wdt_register_callback(cb);
#endif
}

uint32_t Hal_Wdt_GetTimeout(Wdt_Id wdt)
{
#ifdef CONFIG_SDK_WDT
	wdt_switch(wdt);
	return wdt_get_timeout();
#else
	return 0;
#endif
}

uint32_t Hal_Wdt_GetTimeleft(Wdt_Id wdt)
{
#ifdef CONFIG_SDK_WDT
	wdt_switch(wdt);
	return wdt_get_timeleft();
#else
	return 0;
#endif
}

void Hal_Irq_Register(Irq_Num_t nr, Hal_Irq_Callback cb, void *priv)
{
	irq_disable(nr);
	irq_attach(nr, cb, priv);
	irq_cfg_attr(nr, IRQ_ATTR_LEVEL);
	irq_enable(nr);
}

void Hal_Irq_Detach(Irq_Num_t nr)
{
	irq_detach(nr);
}

void Hal_Irq_Enable(Irq_Num_t nr)
{
	irq_enable(nr);
}

void Hal_Irq_Disable(Irq_Num_t nr)
{
	irq_disable(nr);
}

void Hal_Irq_SetPriority(Irq_Num_t nr, uint32_t priority)
{
	irq_set_priority(nr, priority);
}

int32_t Hal_Dma_Alloc_Chan(dma_chan_t chan)
{
#ifdef CONFIG_SDK_DMA
	int32_t reqChan = 0;
	int32_t ret;
	int32_t irq = chan + DMA_CH0_IRQn;

	reqChan = dma_request_chan(chan);
	ret = (reqChan < 0) || (reqChan != chan) ? RET_FAILED : RET_OK;

	if (ret == RET_OK)
		Hal_Irq_Register(irq, dma_interrupt_handler, NULL);

	return ret;
#else
	return RET_OK;
#endif
}

int32_t Hal_Dma_Config(dma_chan_t chan, dma_addr_t sAddr, dma_addr_t dAddr, uint32_t xfer_len,
		       dma_dir_t dir, dma_burst_size_t rBurst, dma_burst_size_t wBurst, dma_ack_bytes_t tx,
		       dma_ack_bytes_t rx, dma_slave_id_t id, dma_priority_t pri)
{
#ifdef CONFIG_SDK_DMA
	int32_t ret = RET_OK;
	struct slave_cfg cfg;

	memset(&cfg, 0, sizeof(cfg));

	ret = dma_xfer_block_add(chan, dir, sAddr, dAddr, xfer_len);
	if (ret)
		return RET_FAILED;

	dma_flush_lli_dcache(chan);
	dma_flush_data_dcache(sAddr, xfer_len);
	dma_invalidate_data_dcache(dAddr, xfer_len);

	cfg.dir          = dir;
	cfg.srcAddrWidth = rBurst;
	cfg.dstAddrWidth = wBurst;
	cfg.txAck        = tx;
	cfg.rxAck        = rx;
	cfg.slaveId      = id;
	cfg.priority     = pri;

	dma_cfg_slave(chan, &cfg);

	return RET_OK;
#else
	return RET_OK;
#endif
}

inline void Hal_Dma_Data_Invalidate(dma_addr_t addr, uint32_t len)
{
#ifdef CONFIG_SDK_DMA
	dma_invalidate_data_dcache(addr, len);
#endif
}

inline void Hal_Dma_Register_Callback(dma_chan_t chan, Hal_Dma_Callback cb)
{
#ifdef CONFIG_SDK_DMA
	dma_register_cb(chan, (chan_xfer_cb_t)cb);
#endif
}

inline void Hal_Dma_Xfer_Start(dma_chan_t chan)
{
#ifdef CONFIG_SDK_DMA
	dma_xfer_start(chan);
#endif
}

inline void Hal_Dma_Xfer_Pending(dma_chan_t chan)
{
#ifdef CONFIG_SDK_DMA
	dma_xfer_pending(chan);
#endif
}

inline void Hal_Dma_Xfer_Multichan_Start(dma_chan_mask_t mask)
{
#ifdef CONFIG_SDK_DMA
	dma_xfer_multi_chan_start(mask);
#endif
}

inline void Hal_Dma_Xfer_Abort(dma_chan_t chan)
{
#ifdef CONFIG_SDK_DMA
	dma_xfer_abort(chan);
#endif
}

inline void Hal_Dma_Xfer_Suspend(dma_chan_t chan)
{
#ifdef CONFIG_SDK_DMA
	dma_xfer_suspend(chan);
#endif
}

inline void Hal_Dma_Xfer_Unsuspend(dma_chan_t chan)
{
#ifdef CONFIG_SDK_DMA
	dma_xfer_unsuspend(chan);
#endif
}

int32_t Hal_Dma_Free_Chan(dma_chan_t chan)
{
#ifdef CONFIG_SDK_DMA
	int32_t ret;

	ret = dma_free_chan(chan);

	return (ret == 0) ? RET_OK : RET_FAILED;
#else
	return RET_OK;
#endif
}

inline void Hal_Dma_Print_Chan_Rate(dma_chan_t chan)
{
#ifdef CONFIG_SDK_DMA
	dma_print_xfer_rate(chan);
#endif
}

int32_t Hal_Sec_Sha256(uint8_t *input, uint32_t len, uint8_t *hash, Sec_Op_Code op)
{
#ifdef CONFIG_SDK_SHA256
	struct sha256_context context;

	if (op == SEC_OP_SW_SHA256) {
		sha256_init(&context);
		sha256_update(&context, input, len);
		sha256_final(&context, hash);
		return RET_OK;
	}
#endif

#ifdef CONFIG_SDK_SEC
	if (op == SEC_OP_HW_SHA256) {
		return sec_sha256_compute(input, len, hash);
	}
#endif

	return RET_OK;
}

int32_t Hal_Sec_Sw_Crypto(uint8_t *input, uint32_t len, uint8_t *output,
					uint8_t *key, uint32_t key_len, Sec_Op_Code op)
{
#if defined (CONFIG_SDK_AES) || defined (CONFIG_SDK_SM4)
	uint8_t i = 0;
#endif

#ifdef CONFIG_SDK_AES
	struct crypto_aes_ctx aes_ctx;
	if (op == SEC_OP_SW_AES_ENC) {
		aes_expandkey(&aes_ctx, key, key_len);
		for (i = 0; i < len; i += 16)
			aes_encrypt(&aes_ctx, output + i, input + i);
	}

	if (op == SEC_OP_SW_AES_DEC) {
		aes_expandkey(&aes_ctx, key, key_len);
		for (i = 0; i < len; i += 16)
			aes_decrypt(&aes_ctx, output + i, input + i);
	}
#endif

#ifdef CONFIG_SDK_SM4
	struct crypto_sm4_ctx sm4_ctx;
	if (op == SEC_OP_SW_SM4_ENC) {
		sm4_expandkey(&sm4_ctx, key, key_len);
		for (i = 0; i < len; i += 16)
			sm4_encrypt(&sm4_ctx, output + i, input + i);
	}

	if (op == SEC_OP_SW_SM4_DEC) {
		sm4_expandkey(&sm4_ctx, key, key_len);
		for (i = 0; i < len; i += 16)
			sm4_decrypt(&sm4_ctx, output + i, input + i);
	}
#endif
	return RET_OK;
}

int32_t Hal_Sec_Hw_Hk_Crypto(uint8_t *input, uint32_t len, uint8_t *key_out,
					uint8_t *output, int seed, Sec_Op_Code op)
{
#ifdef CONFIG_SDK_SEC
	if (op != SEC_OP_HW_HK_AES_ENC && op != SEC_OP_HW_HK_SM4_ENC)
		return RET_FAILED;

	sec_dis_rng();
	sec_set_rng_seed(seed);
	sec_update_rng_seed();
	sec_en_rng();
	sec_update_hw_key();
	sec_set_key_type(HW_KEY);

	sec_get_hw_key(key_out, 16);

	if (op == SEC_OP_HW_HK_AES_ENC)
		return sec_aes_ecb_encrypt(input, len, output);
	else
		return sec_sm4_ecb_encrypt(input, len, output);
#endif
	return RET_OK;
}

int32_t Hal_Sec_Hw_Sk_Crypto(uint8_t *input, uint32_t len, uint8_t *key,
					uint32_t key_len, uint8_t *output, Sec_Op_Code op)
{
#ifdef CONFIG_SDK_SEC
	sec_dis_rng();

	if (op == SEC_OP_HW_SK_AES_ENC) {
		sec_aes_set_ek(key, key_len);
		return sec_aes_ecb_encrypt(input, len, output);
	} else if (op == SEC_OP_HW_SK_SM4_ENC) {
		sec_sm4_set_ek(key, key_len);
		return sec_sm4_ecb_encrypt(input, len, output);
	} else if (op == SEC_OP_HW_SK_AES_DEC) {
		sec_aes_set_dk(key, key_len);
		return sec_aes_ecb_decrypt(input, len, output);
	} else if (op == SEC_OP_HW_SK_SM4_DEC){
		sec_sm4_set_dk(key, key_len);
		return sec_sm4_ecb_decrypt(input, len, output);
	}
#endif
	return RET_OK;
}

int32_t Hal_Efuse_Read(uint32_t addr, uint8_t *data, uint32_t len)
{
#ifdef CONFIG_SDK_EFUSE
	return efuse_read(addr, data, len);
#else
	return 0;
#endif
}

int32_t Hal_Efuse_Write(uint32_t addr, uint8_t *data, uint32_t len)
{
#ifdef CONFIG_SDK_EFUSE
	return efuse_write(addr, data, len);
#else
	return 0;
#endif
}

void Hal_Pmu_RegisterCb(Hal_Pmu_Callback pwron_cb, Hal_Pmu_Callback pwroff_cb)
{
#ifdef CONFIG_SDK_PMU
	pmu_aon_register_callback(pwron_cb, pwroff_cb);
#endif
}

void Hal_Pmu_Enter_Bat_Mode(void)
{
#ifdef CONFIG_SDK_PMU
	pmu_aon_enter_battery_mode();
#endif
}

void Hal_Pmu_Cfg_Pvd_Lv(Pmu_Pvd_Lv lv)
{
#ifdef CONFIG_SDK_PMU
	pmu_active_pvd_lv_cfg(lv);
#endif
}

void Hal_Isp_Start(void)
{
#ifdef CONFIG_SDK_ISP
	isp_start();
#endif
}

void Hal_Saradc_Enable(bool enable)
{
#ifdef CONFIG_SDK_SARADC
	saradc_en(enable);
#endif
}
void Hal_Saradc_temp_threshold_cfg(uint32_t value)
{
#ifdef CONFIG_SDK_SARADC
	saradc_en(value);
#endif
}

void Hal_Saradc_register_int_callback(saradc_int_callback cb)
{
#ifdef CONFIG_SDK_SARADC
	saradc_en_int_callback(cb);
#endif
}

void Hal_Mnt_Configure(uint32_t smp_buf_size, Mnt_Smp_Src smp_src)
{
#ifdef CONFIG_SDK_MONITOR
	mnt_smp_configure(smp_buf_size, smp_src);
#endif
}

void Hal_Mnt_SingleSmp_Start(uint32_t ch_list)
{
#ifdef CONFIG_SDK_MONITOR
	smp_single_para_t para;
	uint8_t ch = 0;
	uint32_t smp_buf_size;
	Mnt_Smp_Src smp_src;

	mnt_smp_configure_get(&smp_buf_size, (enum smp_src_sel *)&smp_src);

	para.ch_list = ch_list;
	para.smp_src = smp_src;

	for (ch = 0; ch < MNT_SMP_CHANNEL_NUM; ch++) {
		if (BIT(ch) & para.ch_list) {
			para.ping_addr[ch] = MNT_PING_BUF_DMEM_ADDR(ch, smp_buf_size);
			para.buf_size[ch] = smp_buf_size;
		}
	}

	mnt_smp_single_start(&para);
#endif
}

void Hal_Mnt_ContSmp_Start(uint32_t ch_list)
{
#ifdef CONFIG_SDK_MONITOR
	smp_cont_para_t para;
	uint8_t ch = 0;
	uint32_t smp_buf_size;
	Mnt_Smp_Src smp_src;

	mnt_smp_configure_get(&smp_buf_size, (enum smp_src_sel *)&smp_src);

	para.ch_list = ch_list;
	para.smp_src = smp_src;

	for (ch = 0; ch < MNT_SMP_CHANNEL_NUM; ch++) {
		if (BIT(ch) & para.ch_list) {
			para.ping_addr[ch] = MNT_PING_BUF_DMEM_ADDR(ch, smp_buf_size);
			para.pang_addr[ch] = MNT_PANG_BUF_DMEM_ADDR(ch, smp_buf_size);
			para.buf_size[ch] = smp_buf_size;
		}
	}

	mnt_smp_cont_start(&para);
#endif
}

void Hal_Mnt_ContSmp_Stop(uint32_t ch_list)
{
#ifdef CONFIG_SDK_MONITOR
	mnt_smp_cont_stop(ch_list);
#endif
}

void Hal_Mnt_ZcpSmp_Start(uint32_t ch_list, uint32_t smp_num, uint8_t *zcp_int)
{
#ifdef CONFIG_SDK_MONITOR
	smp_zcp_para_t para;
	uint8_t ch = 0;
	uint32_t smp_buf_size;
	Mnt_Smp_Src smp_src;

	mnt_smp_configure_get(&smp_buf_size, (enum smp_src_sel *)&smp_src);

	para.ch_list = ch_list;
	para.zcp_int[SMP_MNT_CHANNEL_IN] = ZCP_INT_IN;
	para.zcp_int[SMP_MNT_CHANNEL_IL] = ZCN_INT_IL;

	para.smp_src = SMP_SEL_MONITOR;

	for (ch = 0; ch < MNT_SMP_CHANNEL_NUM; ch++) {
		if (BIT(ch) & para.ch_list) {
			para.ping_addr[ch] = MNT_PING_BUF_DMEM_ADDR(ch, smp_buf_size);
			para.pang_addr[ch] = MNT_PANG_BUF_DMEM_ADDR(ch, smp_buf_size);
			para.buf_size[ch] = smp_buf_size;
			para.zcp_smp_num[ch] = smp_num;
			para.zcp_int[ch] = zcp_int[ch];
		}
	}

	mnt_smp_zcp_start(&para);
#endif
}

void Hal_Mnt_ZcpArcSmp_Start(uint32_t ch_list, uint32_t smp_num, uint8_t *zcp_arc_int)
{
#ifdef CONFIG_SDK_MONITOR
	smp_zcp_arc_para_t para;
	uint8_t ch = 0;
	uint32_t smp_buf_size;
	Mnt_Smp_Src smp_src;

	mnt_smp_configure_get(&smp_buf_size, (enum smp_src_sel *)&smp_src);

	para.ch_list = ch_list;
	para.smp_src = smp_src;

	for (ch = 0; ch < MNT_SMP_CHANNEL_NUM; ch++) {
		if (BIT(ch) & para.ch_list) {
			para.ping_addr[ch] = MNT_PING_BUF_DMEM_ADDR(ch, smp_buf_size);
			para.pang_addr[ch] = MNT_PANG_BUF_DMEM_ADDR(ch, smp_buf_size);
			para.buf_size[ch] = smp_buf_size;
			para.zcp_smp_num[ch] = smp_num;
			para.zcp_arc_int[ch] = zcp_arc_int[ch];
		}
	}

	mnt_smp_zcp_arc_start(&para);
#endif
}

void Hal_Mnt_ZcpSmp_Stop(uint32_t ch_list)
{
#ifdef CONFIG_SDK_MONITOR
	mnt_smp_zcp_stop(ch_list);
#endif
}

void Hal_Mnt_AbnSmp_Start(uint32_t ch_list, uint32_t smp_num, uint8_t *abn_int)
{
#ifdef CONFIG_SDK_MONITOR
	smp_abn_para_t para;
	uint8_t ch = 0;
	uint32_t smp_buf_size;
	Mnt_Smp_Src smp_src;

	mnt_smp_configure_get(&smp_buf_size, (enum smp_src_sel *)&smp_src);

	para.ch_list = ch_list;
	para.smp_src = smp_src;

	for (ch = 0; ch < MNT_SMP_CHANNEL_NUM; ch++) {
		if (BIT(ch) & para.ch_list) {
			para.ping_addr[ch] = MNT_PING_BUF_DMEM_ADDR(ch, smp_buf_size);
			para.buf_size[ch] = smp_buf_size;
			para.abn_smp_num[ch] = smp_num;
			para.abn_int[ch] = abn_int[ch];
		}
	}

	mnt_smp_abn_start(&para);
#endif
}

void Hal_Mnt_AbnArcSmp_Start(uint32_t ch_list, uint32_t smp_num, uint8_t *zcp_abn_int)
{
#ifdef CONFIG_SDK_MONITOR
	smp_abn_arc_para_t para;
	uint8_t ch = 0;
	uint32_t smp_buf_size;
	Mnt_Smp_Src smp_src;

	mnt_smp_configure_get(&smp_buf_size, (enum smp_src_sel *)&smp_src);

	para.ch_list = ch_list;
	para.smp_src = smp_src;

	for (ch = 0; ch < MNT_SMP_CHANNEL_NUM; ch++) {
		if (BIT(ch) & para.ch_list) {
			para.ping_addr[ch] = MNT_PING_BUF_DMEM_ADDR(ch, smp_buf_size);
			para.buf_size[ch] = smp_buf_size;
			para.abn_smp_num[ch] = smp_num;
			para.abn_arc_int[ch] = zcp_abn_int[ch];
		}
	}

	mnt_smp_abn_arc_start(&para);
#endif
}

void Hal_Mnt_ArcPara_Cfg(Mnt_Arc_Basic_Para_t *basic, Mnt_Arc_Filter_Para_t *filter, Mnt_Arc_Err_Check_Para_t *err_check)
{
#ifdef CONFIG_SDK_MONITOR
	mnt_cfg_arc_para((arc_basic_cfg_t *)basic, (arc_filter_para_t *)filter, (arc_error_check_para_t *)err_check);
#endif
}

void Hal_Mnt_RegisterCb(Hal_Mnt_Callback arc_result_get_cb)
{
#ifdef CONFIG_SDK_MONITOR
	mnt_arc_result_cb_register(arc_result_get_cb);
#endif
}

